#include "stack.h"

#include "../xkit.h"

StackHeader *StackInit(losu_vm_t vm, size_t size) {
    StackHeader *out = __xkit_malloc(sizeof(StackHeader));
    out->ref = RefInit(vm);
    out->length = size;
    out->curIndex = 0;
    out->value = (losu_object_t)(__xkit_malloc(sizeof(losu_object) * size));
    return out;
}

void StackFree(losu_vm_t vm, StackHeader *h) {
    RefFree(vm, h->ref);
    __xkit_free(h->value);
    h->curIndex = 0;
    h->length = 0;
    __xkit_free(h);
}

void StackPush(losu_vm_t vm, StackHeader *h, losu_object_t o) {
    if (h->curIndex == h->length) {
        __error_OutOfIndex(vm);
        return ;
    }
    RefIncrease(vm, h->ref, o, 1);
    h->value[h->curIndex] = *o;
    (h->curIndex) ++;
}

void StackPop(losu_vm_t vm, StackHeader *h, losu_object_t target) {
    if (h->curIndex == 0) {
        __error_OutOfIndex(vm);
        return ;
    }
    size_t index = h->curIndex - 1;
    *target = h->value[index];
    RefDecrease(vm, h->ref, h->value + index, 1);
    h->curIndex = index;
}

void StackPeek(losu_vm_t vm, StackHeader *h, losu_object_t target) {
    if (h->curIndex == 0) {
        __error_OutOfIndex(vm);
        return ;
    }
    size_t index = h->curIndex - 1;
    *target = h->value[index];
}